﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using Fcdbas.Core.WCF.TransFile.Contracts.Enums;
using System.IO;
using Fcdbas.Core.WCF.TransFile.Contracts.Models;
using Fcdbas.Core.WCF.TransFile.Contracts.Services;
using Fcdbas.Core.WCF.TransFile.Channels;
using System.ComponentModel;
using Fcdbas.Core.WCF.TransFile.Client.Handlers;

namespace Fcdbas.Core.WCF.TransFile.Client
{
    public class DownLoadFileWorker : IDisposable
    {


        #region ====================================  构造函数 ====================================

        public DownLoadFileWorker()
        {
            initWorker();
        }

        #endregion

        #region ====================================  私有属性 ====================================

        private BackgroundWorker _Worker;

        /// <summary>
        /// 偏移量
        /// </summary>
        private long _OffSet = 0;

        /// <summary>
        /// 增量大小
        /// </summary>
        private long _IncrementSize = 512 * 1024;

        private DownLoadFielInfo _DownLoadInfo;

        private bool _WorkerFlag = false;

        #endregion

        #region ====================================  公共属性 ====================================

        /// <summary>
        /// 增量大小
        /// </summary>
        public long IncrementSize
        {
            get { return _IncrementSize; }
            set { _IncrementSize = value; }
        }

        #endregion

        #region ====================================  公共属性 ====================================

        public event FileLoadEventHandler FileLoadEvent;

        #endregion

        #region ====================================  私有方法 ====================================


        private void initWorker()
        {
            _Worker = new BackgroundWorker();
            _Worker.DoWork += new DoWorkEventHandler(_Worker_DoWork);
        }

        private void OnFileLoadEvent(FileLoadEventArgs e)
        {
            if (FileLoadEvent != null)
            {
                FileLoadEvent(e);
            }
        }


        public long GetRemoteFileSize(SpaceType loadSpaceType, string customFolder, List<string> relativePaths)
        {
            IFileService bll = ChannelContainer.GetChannel<IFileService>();
            return bll.GetDownLoadFileSize(loadSpaceType, customFolder, relativePaths);
        }
        private void _Worker_DoWork(object sender, DoWorkEventArgs e)
        {
            DownLoadFielInfo info = e.Argument as DownLoadFielInfo;
            if (info != null)
            {
                LoadFileInfoModel fileItem = new LoadFileInfoModel();
                fileItem.IsClientBuilderPath = false;
                fileItem.ClientBuilderPath = string.Empty;
                fileItem.LoadType = LoadType.DownLoad;
                fileItem.OffsetIndex = _OffSet;
                fileItem.IncrementSize = 1;
                fileItem.CustomFolder = info.CustomFolder;
                fileItem.FileTitle = info.ServerFileTitle;
                fileItem.Extension = info.Extension;
                fileItem.UpLoadFileType = info.FileType;

                IFileService bll = ChannelContainer.GetChannel<IFileService>();
                FileLoadEventArgs arg = new FileLoadEventArgs();
                arg.Current = 0;
                arg.Size = 0;
                arg.Progress = LoadProgress.Begin;
                OnFileLoadEvent(arg);
                fileItem = bll.DownLoadFile(fileItem);
                if (fileItem.Result != ExecuteResult.Error)
                {
                    fileItem.OffsetIndex = 0;
                    fileItem.IncrementSize = _IncrementSize;
                    while (_OffSet < fileItem.FileSize)
                    {
                        if (!_WorkerFlag)
                        {
                            goto Stop;
                        }

                        try
                        {
                            fileItem = bll.DownLoadFile(fileItem);
                            if (fileItem.Result != ExecuteResult.Error)
                            {
                                if (WriteFile(info, fileItem))
                                {
                                    fileItem.OffsetIndex += fileItem.IncrementData.Length;
                                    fileItem.IncrementData = null;
                                    fileItem.IncrementSize = _IncrementSize;
                                    _OffSet = fileItem.OffsetIndex;
                                    arg.Progress = LoadProgress.Loading;
                                    arg.Size = (int)fileItem.FileSize;
                                    arg.Current = (int)fileItem.OffsetIndex;
                                    OnFileLoadEvent(arg);
                                }
                            }
                        }
                        finally { }
                    }
                    arg.Progress = LoadProgress.Complete;
                    OnFileLoadEvent(arg);
                }

            Stop:
                string empty = string.Empty;
            }
        }

        private bool WriteFile(DownLoadFielInfo local, LoadFileInfoModel model)
        {
            if (local != null && model != null)
            {

                try
                {
                    using (FileStream stream = new FileStream(local.LocalPath, FileMode.OpenOrCreate, FileAccess.ReadWrite))
                    {
                        //if (stream.Length >= model.OffsetIndex)
                        stream.Seek(model.OffsetIndex, SeekOrigin.Current);
                        stream.Write(model.IncrementData, 0, model.IncrementData.Length);
                        stream.Flush();
                    }
                    return true;
                }
                catch { return false; }
            }
            return false;
        }

        /// <summary>
        /// 开始工作单元
        /// </summary>
        private void BeginWorker(DownLoadFielInfo info)
        {
            while (_WorkerFlag)
            {
                if (_Worker != null && !_Worker.IsBusy)
                {
                    _Worker.RunWorkerAsync(info);
                    break;
                }
                Thread.Sleep(300);
            }
        }
        #endregion

        #region ====================================  公共方法 ====================================


        public void Start(DownLoadFielInfo info)
        {

            info.ToolType = ToolType.Start;
            _DownLoadInfo = info;
            _WorkerFlag = true;
            BeginWorker(_DownLoadInfo);
        }

        /// <summary>
        /// 重新启动上传
        /// </summary>
        public void ReStart()
        {
            _DownLoadInfo.ToolType = ToolType.ReStart;
            _WorkerFlag = true;
            BeginWorker(_DownLoadInfo);
        }

        /// <summary>
        /// 继续上传
        /// </summary>
        public void Continue()
        {
            _DownLoadInfo.ToolType = ToolType.Continue;
            _WorkerFlag = true;
            BeginWorker(_DownLoadInfo);
        }

        /// <summary>
        /// 停止上传
        /// </summary>
        public void Stop()
        {
            _WorkerFlag = false;
            Thread.Sleep(100);
        }

        /// <summary>
        /// 删除上传
        /// </summary>
        public void Delete()
        {
            //_UpLoadInfo.ToolType = ToolType.Delete;
            //_WorkerFlag = true;
            //BeginWorker(_UpLoadInfo);
        }


        public void Dispose()
        {
            _WorkerFlag = false;

            Thread.Sleep(100);
            if (_Worker != null)
                _Worker.Dispose();
            GC.Collect();

        }

        #endregion

    }
}
